#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
PyInstaller打包脚本
用于将微信告警推送系统打包成exe可执行文件
"""

import os
import sys
import shutil
import subprocess
from pathlib import Path
from datetime import datetime

# 尝试导入logger，如果失败则使用print函数
try:
    from src.utils.logger import logger
except ImportError:
    # 定义一个简单的logger替代
    class SimpleLogger:
        def info(self, msg):
            print(f"[INFO] {msg}")
        def error(self, msg):
            print(f"[ERROR] {msg}")
        def warning(self, msg):
            print(f"[WARNING] {msg}")
    
    logger = SimpleLogger()

def clean_build_dirs():
    """清理构建目录"""
    # 先尝试删除可能被占用的日志文件
    dist_log_file = Path('dist') / 'logs' / 'wechat_alarm.log'
    if dist_log_file.exists():
        try:
            logger.info(f"尝试删除日志文件: {dist_log_file}")
            dist_log_file.unlink()
            logger.info(f"成功删除日志文件: {dist_log_file}")
        except Exception as e:
            logger.warning(f"无法删除日志文件 {dist_log_file}: {e}")
            logger.warning("日志文件可能被占用，请确保应用程序已关闭")
    
    dirs_to_clean = ['build', 'dist', '__pycache__']
    for dir_name in dirs_to_clean:
        if os.path.exists(dir_name):
            logger.info(f"清理目录: {dir_name}")
            try:
                # 如果是dist目录，先检查日志文件
                if dir_name == 'dist' and os.path.exists(os.path.join('dist', 'logs', 'wechat_alarm.log')):
                    try:
                        # 尝试打开文件，如果可以打开，说明没有被占用
                        with open(os.path.join('dist', 'logs', 'wechat_alarm.log'), 'a'):
                            pass
                    except PermissionError:
                        logger.warning(f"日志文件被占用，跳过删除dist目录")
                        continue
                shutil.rmtree(dir_name)
            except Exception as e:
                logger.warning(f"清理目录 {dir_name} 失败: {e}")
                # 如果是权限问题，可能是文件被占用，尝试逐个删除文件
                if isinstance(e, PermissionError):
                    logger.info(f"尝试逐个删除 {dir_name} 目录中的文件...")
                    try:
                        for root, dirs, files in os.walk(dir_name, topdown=False):
                            for file in files:
                                try:
                                    file_path = os.path.join(root, file)
                                    os.remove(file_path)
                                    logger.info(f"删除文件: {file_path}")
                                except Exception as e2:
                                    logger.warning(f"无法删除文件 {file_path}: {e2}")
                        # 再次尝试删除目录
                        shutil.rmtree(dir_name, ignore_errors=True)
                    except Exception as e3:
                        logger.warning(f"清理目录 {dir_name} 失败，将继续执行: {e3}")

def create_spec_file():
    """创建PyInstaller spec文件"""
    spec_content = '''# -*- mode: python ; coding: utf-8 -*-

block_cipher = None

a = Analysis(
    ['src/main.py'],
    pathex=[],
    binaries=[],
    datas=[
        # 不包含config目录，它将单独复制
        ('logs', 'logs'),  # 包含logs目录
    ],
    hiddenimports=[
        'pymysql',
        'apscheduler',
        'apscheduler.triggers.cron',
        'apscheduler.schedulers.background',
        'tkinter',
        'tkinter.ttk',
        'tkinter.messagebox',
        'tkinter.scrolledtext',
        'win32gui',
        'win32con',
        'win32api',
        'win32com',
        'win32com.client',
        'pythoncom',
        'comtypes',
        'comtypes.client',
        'pywinauto',
        'pywinauto.findwindows',
        'pywinauto.application',
        'pywinauto.controls',
        'pywinauto.controls.uiawrapper',
        'pywinauto.base_wrapper',
        'pywinauto.timings',
        'pywinauto.keyboard',
        'pywinauto.mouse',
        'pywinauto.win32functions',
        'pywinauto.win32defines',
        'pywinauto.win32structures',
        'pywinauto.uia_defines',
        'pywinauto.uia_element_info',
        'pywinauto.backend',
        'six',
    ],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    win_no_prefer_redirects=False,
    win_private_assemblies=False,
    cipher=block_cipher,
    noarchive=False,
)

pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.zipfiles,
    a.datas,
    [],
    name='微信告警推送系统',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=False,  # 设置为False以隐藏控制台窗口
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
    icon='resources/app_icon.ico' if os.path.exists('resources/app_icon.ico') else None,
)
'''
    
    with open('WeChatAlarm.spec', 'w', encoding='utf-8') as f:
        f.write(spec_content)
    logger.info("创建PyInstaller spec文件: WeChatAlarm.spec")

def run_pyinstaller():
    """运行PyInstaller打包"""
    try:
        logger.info("开始PyInstaller打包...")
        
        # 创建startupinfo对象以隐藏命令行窗口
        startupinfo = None
        if sys.platform == 'win32':
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            startupinfo.wShowWindow = 0  # SW_HIDE
        
        result = subprocess.run([
            sys.executable, '-m', 'PyInstaller',
            '--clean',
            'WeChatAlarm.spec'
        ], check=True, capture_output=True, text=True,
           startupinfo=startupinfo if startupinfo else None)
        
        logger.info("PyInstaller打包成功!")
        logger.info(f"输出: {result.stdout}")
        
        return True
    except subprocess.CalledProcessError as e:
        logger.error(f"PyInstaller打包失败: {e}")
        logger.error(f"错误输出: {e.stderr}")
        return False

def copy_config_to_dist():
    """仅复制config.ini文件到dist目录"""
    dist_dir = Path('dist')
    if not dist_dir.exists():
        logger.error("dist目录不存在，打包可能失败")
        return False
    
    # 复制config.ini文件
    config_file = Path('config/config.ini')
    if config_file.exists():
        dist_config_dir = dist_dir / 'config'
        if not dist_config_dir.exists():
            dist_config_dir.mkdir(parents=True, exist_ok=True)
        
        # 复制config.ini文件
        shutil.copy2(config_file, dist_config_dir / 'config.ini')
        logger.info("✅ 复制文件: config/config.ini -> dist/config/config.ini")
        return True
    else:
        logger.warning("config/config.ini文件不存在，将创建空配置文件")
        
        # 创建空的config目录和config.ini文件
        dist_config_dir = dist_dir / 'config'
        if not dist_config_dir.exists():
            dist_config_dir.mkdir(parents=True, exist_ok=True)
        
        # 创建基本的config.ini文件
        with open(dist_config_dir / 'config.ini', 'w', encoding='utf-8') as f:
            f.write(f"; 微信告警推送系统配置文件\n")
            f.write(f"; 创建时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
            f.write("[system]\n")
            f.write("log_level = INFO\n\n")
            f.write("[wechat]\n")
            f.write("contacts = []\n\n")
            f.write("[database]\n")
            f.write("host = localhost\n")
            f.write("port = 3306\n")
            f.write("username = root\n")
            f.write("password = \n")
            f.write("database = alarm_db\n")
            f.write("table_name = t_warning_info\n\n")
            f.write("[scheduler]\n")
            f.write("check_minutes = 0,15,30,45\n")
            f.write("resend_daily_alarms = false\n")
        
        logger.info("✅ 创建默认配置文件: dist/config/config.ini")
        return True

def create_readme():
    """创建README文件"""
    dist_dir = Path('dist')
    if not dist_dir.exists():
        logger.error("dist目录不存在，打包可能失败")
        return False
    
    # 创建README文件
    readme_content = '''# 微信告警推送系统

## 使用说明

1. 双击 `微信告警推送系统.exe` 启动系统
2. 系统会自动检测微信登录状态，如果未登录会提示登录
3. 配置文件位于 `config/config.ini`，可以根据需要修改

## 配置说明

- `system` 部分：系统设置
  - `log_level`：日志级别，可选值为 DEBUG、INFO、WARNING、ERROR、CRITICAL

- `wechat` 部分：微信设置
  - `contacts`：联系人列表，可以在程序界面中设置

- `database` 部分：数据库设置
  - `host`：数据库主机
  - `port`：数据库端口
  - `username`：数据库用户名
  - `password`：数据库密码
  - `database`：数据库名
  - `table_name`：告警表名

- `scheduler` 部分：调度设置
  - `check_minutes`：检查分钟，格式为逗号分隔的分钟值，如 0,15,30,45
  - `resend_daily_alarms`：是否重复发送当日告警，true 或 false

## 注意事项

1. 系统需要微信桌面版已安装并登录
2. 首次使用时，请确保配置正确的数据库连接信息
3. 日志文件位于程序目录下的 `logs` 文件夹中
'''
    
    with open(dist_dir / 'README.md', 'w', encoding='utf-8') as f:
        f.write(readme_content)
    
    logger.info("✅ 创建README文件: dist/README.md")
    return True

def main():
    """主函数"""
    logger.info("🚀 开始打包微信告警推送系统...")
    
    # 清理构建目录
    clean_build_dirs()
    
    # 创建spec文件
    create_spec_file()
    
    # 运行打包
    if run_pyinstaller():
        # 复制配置文件
        config_success = copy_config_to_dist()
        
        # 创建README文件
        readme_success = create_readme()
        
        # 创建logs目录
        logs_dir = Path('dist') / 'logs'
        if not logs_dir.exists():
            logs_dir.mkdir(parents=True, exist_ok=True)
            logger.info("✅ 创建日志目录: dist/logs")
        
        if config_success and readme_success:
            logger.info("✅ 打包完成！可执行文件位于: dist/微信告警推送系统.exe")
            logger.info("✅ 配置文件位于: dist/config/config.ini")
            logger.info("✅ 使用说明位于: dist/README.md")
            logger.info("✅ 日志目录位于: dist/logs")
        else:
            logger.warning("⚠️ 打包完成，但部分文件创建失败")
        return 0
    else:
        logger.error("❌ 打包失败，请检查错误信息")
        return 1

if __name__ == '__main__':
    sys.exit(main()) 